package com.gree.shyun.server.db;


import com.gree.shyun.server.Config;
import com.gree.shyun.server.db.annotation.Column;
import com.gree.shyun.server.db.bean.ColumnDesc;
import com.gree.shyun.server.db.ex.DbException;
import com.gree.shyun.server.db.sqlite.DbModelSelector;
import com.gree.shyun.server.db.sqlite.Selector;
import com.gree.shyun.server.db.sqlite.SqlInfo;
import com.gree.shyun.server.db.sqlite.WhereBuilder;
import com.gree.shyun.server.db.table.DbModel;
import com.gree.shyun.server.db.util.LogUtils;
import com.gree.shyun.server.db.util.TextUtils;
import com.gree.shyun.util.json.JsonMananger;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.jar.JarEntry;


public class DbHelper {
    private static DbManager db ;

    static {
        getInstance();
    }
    /**
     * 初始化数据库并获得DB对象
     * @return
     */
    public static DbManager getInstance(){
        if (db == null) {
            synchronized (DbHelper.class) {
                if (db == null) {
                    db = DbManager.getInstance(Config.dbName);
                    db.configAllowTransaction(true);
                    db.configDebug(Config.debug);
                    createTable();
                }
            }
        }
        return db;
    }
    //获得表类
    public static List<Class> getTables(){
        if(Config.table!=null&& Config.table.length>0) {
            return Arrays.asList(Config.table);
        }
        return new ArrayList<>();
    }
    /**
     * 获得所有表名
     * @return
     */
    public static List<String> getTableNames(){
        List<String> tableNames = new ArrayList<>();
        List<Class> tables = getTables();
        for(int i = 0;i<tables.size();i++){
            Class cla = tables.get(i);
            String tableName = db.getTableName(cla);
            tableNames.add(tableName);
        }
        return tableNames;
    }


    /**
     * 初始化
     */
    public static void initData(){
        try {
            Config.initData();
        }catch (Exception e){
            printLog( e.getMessage());
        }
    }

    /**
     * 删除创建的表
     * @return
     */
    public static boolean dropTable(){
        try {
            for(Class cla:getTables()){
                db.dropTable(cla);
            }
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 创建数据库表
     * @return
     */
    public static boolean createTable(){
        List<Class> tables = getTables();
        if(tables.size()==0){
            return false;
        }
        try {
            boolean isEx = db.tableIsExist(tables.get(0));
            for(Class cla:tables){
                db.createTableIfNotExist(cla);
            }
            if(!isEx){
                //执行初始化
                initData();
            }
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    //创建表
    public static boolean createTable(Class<?> cla){
        try {
            db.createTableIfNotExist(cla);
            return true;
        }catch (DbException e){
            printLog( e.getMessage());
        }
        return false;
    }

    /**
     * 通过ID查询单条数据
     * @param cls
     * @param id
     * @param <T>
     * @return
     */
    public static <T>T findById(Class<?> cls, Object id){
        Object entity = null;
        try{
            entity = db.findById(cls,id);
        }catch (DbException e){
            printLog( e.getMessage());
        }
        return (T)entity;
    }


    /**
     * 根据条件 查找单个
     * @param selector
     * @return
     */
    public static <T>T findFirst(Selector selector){
        Object entity = null;
        try{
            entity = db.findFirst(selector);
        }catch (DbException e){
            printLog( e.getMessage());
        }
        return (T)entity;
    }

    /**
     * 保存单条 返回id
     * @param obj
     * @return
     */
    public static <T>T saveBindingId(Object obj){
        Object id =null;
        try{
            boolean saved = db.saveBindingId(obj);
            if(saved){
                return (T)obj;
            }
        }catch (DbException e){
            printLog( e.getMessage());
        }
        return null;
    }

    /**
     * 保存单条
     * @param obj
     * @return
     */
    public static boolean save(Object obj){
        try{
            db.save(obj);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 保存数据,单条或多条
     * @param entity
     * @return
     */
    public static boolean save(List<?> entity){
        if(entity==null||entity.size()==0){
            return false;
        }
        try{
            db.saveAll(entity);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 保存数据,单条或多条 并返回ID
     * @param entity
     * @return
     */
    public static List<?> saveBindingIdAll(List<?> entity){
        if(entity==null||entity.size()==0){
            return null;
        }
        try{
            db.saveBindingIdAll(entity);
            return entity;
        }catch (DbException e){
            printLog( e.getMessage());
        }
        return null;
    }

    /**
     *  全部替换（慎用）
     *  如果不存在就新建，如果存在就全部替换
     *  注意 ：如果没赋值的字段也会被全部替换
     * @param obj
     * @return
     */
    public static boolean replace(Object obj){
        try{
            db.replace(obj);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 全部替换 同上
     * @param entities
     * @return
     */
    public static boolean replaceAll(List<?> entities){
        try{
            db.replaceAll(entities);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 保存或更新，全部
     * @param entity
     * @return
     */
    public static boolean saveOrUpdate(List<?> entity,String... updateColumnNames){
        if(entity==null||entity.size()==0){
            return false;
        }
        try{
            db.saveOrUpdateAll(entity,updateColumnNames);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * 保存单条
     * @param obj
     * @return
     */
    public static boolean saveOrUpdate(Object obj,String... updateColumnNames){
        try{
            db.saveOrUpdate(obj,updateColumnNames);
        }catch (DbException e){
            printLog(  e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新单条数据
     * @param entity
     * @param whereBuilder
     * @param updateColumnNames
     * @return
     */
    public static boolean update(Object entity, WhereBuilder whereBuilder, String... updateColumnNames){
        try {
            db.update(entity,whereBuilder,updateColumnNames);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新单条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean update(Object entity, String... updateColumnNames){
        try {
            db.update(entity,updateColumnNames);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新多条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean updateAll(List<?> entity, WhereBuilder whereBuilder, String... updateColumnNames){
        try {
            db.updateAll(entity,whereBuilder,updateColumnNames);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 更新多条数据
     * @param entity
     * @param updateColumnNames
     * @return
     */
    public static boolean updateAll(List<?> entity, String... updateColumnNames){
        try {
            db.updateAll(entity,updateColumnNames);
        }catch (DbException e){
            printLog( e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 删除单条
     * @param obj
     * @return
     */
    public static boolean delete(Object obj){
        try {
            db.delete(obj);
        }catch (DbException e){
            printLog(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 删除全部
     * @param cla
     * @return
     */
    public static boolean deleteAll(Class<?> cla){
        try {
            db.deleteAll(cla);
        }catch (DbException e){
            printLog(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 通过ID删除
     * @param cla
     * @param id
     * @return
     */
    public static boolean deleteById(Class<?> cla, Object id){
        try {
            db.deleteById(cla,id);
        }catch (DbException e){
            printLog(e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 删除数据 单条或多条
     * @param entity
     * @return
     */
    public static boolean delete(List<?> entity){
        if(entity.size()==0){
            return false;
        }
        try{
            db.deleteAll(entity);
        }catch (DbException e){
            printLog(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 按条件删除某张表的数据
     * @param cls
     * @param whereBuilder
     * @return
     */
    public static boolean delete(Class<?> cls, WhereBuilder whereBuilder){
        try{
            db.delete(cls,whereBuilder);
        }catch (DbException e){
            printLog(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 查询某张表的数据
     * @param cls
     * @return
     */
    public static long count(Class<?> cls){
        long count = 0l;
        try{
            count = db.count(cls);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return count;
    }

    /**
     * 根据条件查询数量
     * @param selector
     * @return
     */
    public static long count(Selector selector){
        long count = 0l;
        try{
            count = db.count(selector);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return count;
    }

    /**
     * 查询某张表的所有数据
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> List<T> findAll(Class<T> cls){
        List<T> list = null;
        try{
            list = db.findAll(cls);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return list;
    }



    /**
     * 根据条件查询某些数据
     * @param selector
     * @param <T>
     * @return
     */
    public static <T> List<T> findAll(Selector selector){
        List<T> list = null;
        try{
            list = db.findAll(selector);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return list;
    }

    /**
     * 判断表是否存在
     * @param cla
     * @return
     */
    public static boolean tableIsExist(Class<?> cla){
        try {
            return db.tableIsExist(cla);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return false;
    }


    /**
     * 通用模型 查询第一条数据
     * @param sql
     * @return
     */
    public static DbModel findDbModelFirst(String sql){
        try {
            SqlInfo sqlInfo = new SqlInfo();
            sqlInfo.setSql(sql);
            return  db.findDbModelFirst(sqlInfo);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return null;
    }

    /**
     *  复杂查询
     * @param selector
     * @return
     */
    public static DbModel findDbModelFirst(DbModelSelector selector){
        try {
            return  db.findDbModelFirst(selector);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return null;
    }

    /**
     *  复杂查询
     * @param selector
     * @return
     */
    public static  List<DbModel> findDbModelAll(DbModelSelector selector){
        try {
            return  db.findDbModelAll(selector);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return null;
    }

    /**
     * 复杂查询
     * @param sql
     * @return
     */
    public static  List<DbModel> findDbModelAll(String sql){
        try {
            SqlInfo selector = new SqlInfo();
            selector.setSql(sql);
            return  db.findDbModelAll(selector);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return null;
    }

    /**
     * 执行非查询sql
     * @param sqls
     */
    public static void exec_nonquery(String... sqls){
        for(String sql:sqls){
            if(TextUtils.isEmpty(sql)){
                return;
            }
            try {
                db.execNonQuery(sql);
            }catch (DbException e){
                printLog(sql,e.getMessage());
            }
        }
    }

    /**
     * 直接执行查询
     * @param selector
     * @return
     */
    public  List<Map<String,Object>> exec(Selector selector) {
        return exec(selector.toString());
    }

    /**
     * 直接执行sql
     * @param sql
     * @return
     */
    public List<Map<String,Object>> exec(String sql){
        if(TextUtils.isEmpty(sql)){
            return null;
        }
        try {
            return db.exec(sql);
        }catch (DbException e){
            printLog(sql,e.getMessage());
        }
        return null;
    }
    public static String getTableName(Class c){
        return db.getTableName(c);
    }

    /**
     *  获取表列名
     * @param table
     * @return
     */
    public static   List<String> getTableColumn(Class table){
        if(table==null){
            return null;
        }
        try {
            return  db.getTableCloumn(table);
        }catch (DbException e){
            printLog(e.getMessage());
        }
        return null;
    }


    /**
     * 获取表 字段描述
     * @param table
     * @return
     */
    public static List<ColumnDesc> getTableColumnDesc(Class table){
        List<ColumnDesc> columnDescs = new ArrayList<>();
        List<String> cloumns = getTableColumn(table);
        Field[] fields = table.getDeclaredFields();
        Map<String,String> map = new HashMap<>();
        for(Field field:fields){
            field.setAccessible(true);
            Annotation annotation  = field.getAnnotation(Column.class);
            if(annotation!=null){
                Column column = (Column)annotation;
                map.put(field.getName(),column.desc());
            }
        }
        //通过数据库取出来的 按顺序输出
        for(String cloumn:cloumns){
            String desc = map.get(cloumn);
            if(desc!=null&&!"".equals(desc)) {
                ColumnDesc columnDesc = new ColumnDesc();
                columnDesc.setName(cloumn);
                columnDesc.setDesc(desc);
                columnDescs.add(columnDesc);
            }
        }
        return columnDescs;
    }

    /**
     * 打印日志
     * @param args
     */
    private static void printLog(String ...args){
        String aa = "";
        for(String s:args){
            aa+="->"+s;
        }
        System.out.println(aa);
        //LogUtils.e(aa);
    }
}
